﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Xml.Serialization;

namespace HgCo.WindowsLive.SkyDrive.TotalCommander.Plugins.Support
{
    /// <summary>
    /// Represents the configuration for SkyDriveWfx.
    /// </summary>
    [XmlRoot(ElementName="configuration", Namespace="")]
    public class SkyDriveWfxConfiguration
    {
        #region Fields
        
        /// <summary>
        /// The default SkyDriveWfx configuration.
        /// </summary>
        public readonly static SkyDriveWfxConfiguration Default = new SkyDriveWfxConfiguration
            {
                ApplicationSettings = new SkyDriveWfxApplicationSetting[]
                {
                    new SkyDriveWfxApplicationSetting { Key = "UserName", Value = "" },
                    new SkyDriveWfxApplicationSetting { Key = "UserPassword", Value = "" },
                    new SkyDriveWfxApplicationSetting { Key = "CID", Value = "" },
                    new SkyDriveWfxApplicationSetting { Key = "ConnectionType", Value = "Private" }
                }
            };

        #endregion

        #region Properties

        /// <summary>
        /// Gets the configuration file.
        /// </summary>
        /// <value>The configuration file.</value>
        public static FileInfo ConfigurationFile
        {
            get
            {
                string configFileName = String.Format(
                    CultureInfo.InvariantCulture,
                    "{0}.config",
                    System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name);
                FileInfo fiConfig = new FileInfo(Path.Combine(
                    AppDomain.CurrentDomain.BaseDirectory,
                    configFileName));
                return fiConfig;
            }
        }

        /// <summary>
        /// Gets or sets the list of application settings.
        /// </summary>
        /// <value>The list of application settings.</value>
        [XmlArray(ElementName = "appSettings")]
        [XmlArrayItem(ElementName = "add")]
        public SkyDriveWfxApplicationSetting[] ApplicationSettings { get; set; }

        /// <summary>
        /// Gets or sets the name of the user.
        /// </summary>
        /// <value>The name of the user.</value>
        [XmlIgnore()]
        public string UserName
        {
            get
            {
                return GetApplicationSettingValue("UserName");
            }
            set
            {
                SetApplicationSettingValue("UserName", value);
            }
        }

        /// <summary>
        /// Gets or sets the password of the user.
        /// </summary>
        /// <value>The password.</value>
        [XmlIgnore()]
        public string UserPassword
        {
            get
            {
                return GetApplicationSettingValue("UserPassword");
            }
            set
            {
                SetApplicationSettingValue("UserPassword", value);
            }
        }

        /// <summary>
        /// Gets or sets the Windows Live Identifier (CID).
        /// </summary>
        /// <value>The Cid.</value>
        [XmlIgnore()]
        public string Cid
        {
            get
            {
                return GetApplicationSettingValue("CID");
            }
            set
            {
                SetApplicationSettingValue("CID", value);
            }
        }

        /// <summary>
        /// Gets or sets the connection type.
        /// </summary>
        /// <value>The connection type.</value>
        [XmlIgnore()]
        public SkyDriveWfxConnectionType ConnectionType
        {
            get
            {
                SkyDriveWfxConnectionType connectionType = SkyDriveWfxConnectionType.Private;
                try
                {
                    connectionType = (SkyDriveWfxConnectionType)Enum.Parse(
                        typeof(SkyDriveWfxConnectionType),
                        GetApplicationSettingValue("ConnectionType"),
                        true);
                }
                catch { }
                return connectionType;
            }
            set
            {
                SetApplicationSettingValue("ConnectionType", value.ToString());
            }
        }

        #endregion

        #region Instance Methods

        /// <summary>
        /// Gets the application setting by key.
        /// </summary>
        /// <param name="key">The key of the application setting.</param>
        /// <returns>The application setting.</returns>
        public SkyDriveWfxApplicationSetting GetApplicationSetting(string key)
        {
            foreach (SkyDriveWfxApplicationSetting appSet in ApplicationSettings)
                if (appSet.Key.Equals(key, StringComparison.CurrentCultureIgnoreCase))
                    return appSet;
            return null;
        }

        /// <summary>
        /// Gets the value of an application setting by key.
        /// </summary>
        /// <param name="key">The key of the application setting.</param>
        /// <returns>The value of the application setting.</returns>
        public string GetApplicationSettingValue(string key)
        {
            foreach (SkyDriveWfxApplicationSetting appSet in ApplicationSettings)
                if (appSet.Key.Equals(key, StringComparison.CurrentCultureIgnoreCase))
                    return appSet.Value;
            return String.Empty;
        }

        /// <summary>
        /// Sets the value of an application setting by key.
        /// </summary>
        /// <param name="key">The key of the application setting.</param>
        /// <param name="value">The value of the application setting.</param>
        public void SetApplicationSettingValue(string key, string value)
        {
            foreach (SkyDriveWfxApplicationSetting appSet in ApplicationSettings)
                if (appSet.Key.Equals(key, StringComparison.CurrentCultureIgnoreCase))
                {
                    appSet.Value = value;
                    return;
                }
            List<SkyDriveWfxApplicationSetting> lAppSet =
                new List<SkyDriveWfxApplicationSetting>(ApplicationSettings.Length);
            lAppSet.AddRange(ApplicationSettings);
            lAppSet.Add(new SkyDriveWfxApplicationSetting
            {
                Key = key,
                Value = value
            });
            ApplicationSettings = lAppSet.ToArray();
        }

        /// <summary>
        /// Saves the configuration.
        /// </summary>
        public void Save()
        {
            Save(this);
        }

        #endregion

        #region Static Methods

        /// <summary>
        /// Loads the configuration.
        /// </summary>
        /// <returns>The configuration.</returns>
        public static SkyDriveWfxConfiguration Load()
        {
            SkyDriveWfxConfiguration config = null;
            FileInfo fiConfig = ConfigurationFile;

            if (fiConfig.Exists)
                try
                {
                    using (FileStream fsr = fiConfig.OpenRead())
                    {
                        XmlSerializer xs = new XmlSerializer(typeof(SkyDriveWfxConfiguration));
                        config = xs.Deserialize(fsr) as SkyDriveWfxConfiguration;
                    }
                }
                catch { }

            if (config == null)
                config = Default;

            return config;
        }

        /// <summary>
        /// Saves the configuration.
        /// </summary>
        /// <param name="config">The configuration to save.</param>
        public static void Save(SkyDriveWfxConfiguration config)
        {
            if (config != null)
            {
                FileInfo fiConfig = ConfigurationFile;
                try
                {
                    using (FileStream fsw = fiConfig.Open(FileMode.OpenOrCreate))
                    {
                        XmlSerializerNamespaces xsns = new XmlSerializerNamespaces();
                        xsns.Add(String.Empty, String.Empty);
                        XmlSerializer xs = new XmlSerializer(typeof(SkyDriveWfxConfiguration));
                        xs.Serialize(fsw, config, xsns);
                    }
                }
                catch { }
            }
        }

        #endregion
    }
}
